package com.neveu.android.ds.socketmessenger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class NetServent {

	Socket clientSock;
	ServerSocket serverSock;
	private String loopbackIP;
	private boolean connected;
	private int connectPort;
	private PrintWriter pw;
	private MessageListener msgListener;
	private BufferedReader in;

	
	public NetServent(String loopbackIP, String emulatorIP, final int listenPort, int clientPort)
	{
		connected = false;
		this.loopbackIP = loopbackIP;
		this.connectPort = clientPort;
		

		new Thread(new Runnable() {
			public void run()
			{
				if(!connect())
				{
					try {
						serverSock = new ServerSocket(listenPort);
					}catch(IOException e){
						System.err.println("Could not establish listening socket on port " + listenPort);
					}
					
					try {
							clientSock = serverSock.accept();
							connected = true;
						}catch(IOException e) {
							/* this is caught whether there is a legitimate socket issue, or if serverSock
							 * has been explicitly closed. Either way, readInput() is not reached, which is what we want.
							 */
		//					System.err.println("Could not establish listening socket on port ");
						}
				}
			
				readInput();
			}}).start();
	}
	
	public boolean connect()
	{
		try{
			clientSock = new Socket(loopbackIP, connectPort);
			
		} catch (UnknownHostException e) {
            System.err.println("Don't know about host: " + loopbackIP + ".");
            return false;
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for "
                               + "the connection to: " + loopbackIP + ".");
            return false;
        }
		
		connected = true;
		return true;
	}
	
	public void sendMessage(String msg)
	{
		if(pw == null && connected)
		{
			try{
				pw = new PrintWriter(clientSock.getOutputStream(), true);
	        } catch (IOException e) {
	        	System.err.println("Could not get socket output stream");
	        }
		}
		
		pw.println(msg);
	}
	
	public synchronized void readInput()
	{
		String inStr = "";
		
		try{
			in = new BufferedReader(
				    new InputStreamReader(
				    		clientSock.getInputStream()));

//			while(clientSock.isBound())

			/* How to nicely interrupt this blocking call when we wish to exit?? */
				while((inStr = in.readLine()) != null)
				{
					
					if(msgListener != null)
						msgListener.receiveMessage(inStr + "\n");
					else
						System.out.println(inStr);
				}

				in.close();
				
		}catch (IOException e) {
//			System.err.println(e.getMessage());
		}
		finally{
		}
	}
		
	
	
	public void disconnect()
	{
		try{
			in.close();
			clientSock.close();
			serverSock.close();
		}catch(IOException e)
		{
			System.err.println(e.getMessage());
		}
	}
	
	public void setMessageListener(MessageListener ml)
	{
		msgListener = ml;
	}
}
